Android Browser App 源码分析(三)之UI篇第一讲

Android Native Browser的界面还是比较单一,比较少的。主要体现为:主界面(主要用于加载网页)、设置页面(用于设置浏览器中各个属性,比如是否启用JavaScript、是否保存密码等)、书签&历史记录页面(展示书签以及访问网页的历史记录)。


首先从代码层面分析下主界面的UI逻辑实现,看看到底是如何加载网页的。



(一)基础架构

Browser定义了UI接口来统管整个主界面的操作,以及对Activity生命周期发生变化的处理。
因Browser App同时也要兼容平板设备,所以,这里又抽象出一个抽象类BaseUi来实现手机与平板公共通用的部分,然后将差异性的方法通过派生类PhoneUi与XLargeUi来实现。


Browser主界面头部会有一个标题栏,主要用于输入网址、保存书签,因为平板与手机的尺寸是不同的,对应的头部Tab页导航展示也就不同了,所以Browser内部又声明了NavigationBarPhone、NavigationBarTablet类来进行处理,他们继承于NavigationBarBase类。


整个结构关系如下:



(二)主界面如何Load出来的

启动页:BrowserActivity::onCreate()
初始化Controller 对象


然后调用Controller start方法


然后调用CrashRecoveryHandler startRecovery方法


CrashRecoveryHandler实例的初始化调用在Controller构造函数中:
mCrashRecoveryHandler = CrashRecoveryHandler.initialize(this); //实例化CrashRecoveryHandler对象,CrashRecoveryHandler构造函数中同时又创建了foregroundHandler和backgroundHandler


mCrashRecoveryHandler.preloadCrashState();
//mBackgroundHandler.sendEmptyMessage(MSG_PRELOAD_STATE); 
调用loadCrashState,从STATE_FILE(browser_state.parcel)文件中读入到mRecoveryState中


调用mController.doStart(mRecoveryState, intent); 将mRecoveryState传递过去


然后对mRecoveryState中的lastActiveDate进行判断,如果最后一次浏览器的使用时间在24小时内,否则的话销毁所有剩余的隐身标签页。


调用mTabControl.canRestoreState来获取TabId
如果等于-1,执行CookieManager.getInstance().removeSessionCookie()


然后调用GoogleAccountLogin.startLoginIfNeeded进行登录
如果已经登录或者没有找到账号,直接执行runnable.run 方法
否则执行登录操作


onPreloginFinished 方法:
如果tabId等于-1(默认的情况下第一次进来为-1):
如果intent为null:调用openTabToHomePage方法,打开主页
如果intent不为null:获取urlData,如果为空:调用openTabToHomePage方法,打开主页
否则打开Tab,加载对应的urlData


调用openTabToHomePage:
openTab(mSettings.getHomePage(), false, true, false);


最终会调用这个openTab(String url, boolean incognito, boolean setActive,boolean useCurrent, Tab parent)方法:


通过createNewTab创建一个Tab对象
内部是通过TabControl.createNewTab来进行创建
createNewTab(boolean privateBrowsing)---> createNewTab(Bundle state, boolean privateBrowsing) ---->  createNewWebView实例化WebView对象---> mController.getWebViewFactory().createWebView(privateBrowsing)
----> BrowserWebViewFactory.createWebView 创建WebView
-----> instantiateWebView、initWebViewSettings


WebView创建完毕之后,开始实例化一个Tab对象,并添加到mTabs集合中:
Tab t = new Tab(mController, w, state);
mTabs.add(t);


调用Controller.onSetWebView ---> mUi.onSetWebView(tab, view);
----->BaseUi.onSetWebView


然后container = mActivity.getLayoutInflater().inflate(R.layout.tab, mContentView, false); 创建装载WebView的Tab容器



之后调用  t.putInBackground(); 先把标签放入后台




调用addTab()-->mUi.addTab 将tab传递到对应的UI中
这个方法PhoneUi没有重写,XLargeUi重写了。




然后调用 Controller.setActiveTab(tab) --->  mTabControl.setCurrentTab(tab)、mUi.setActiveTab(tab)


--->PhoneUi::setActiveTab


--->BaseUi::setActiveTab


--->attachTabToContentView(tab)

protected void attachTabToContentView(Tab tab) {
        if ((tab == null) || (tab.getWebView() == null)) {
            return;
        }
        View container = tab.getViewContainer();
        WebView mainView  = tab.getWebView();
        // Attach the WebView to the container and then attach the
        // container to the content view.
        FrameLayout wrapper =
                (FrameLayout) container.findViewById(R.id.webview_wrapper);
        ViewGroup parent = (ViewGroup) mainView.getParent();
        if (parent != wrapper) {
            if (parent != null) {
                parent.removeView(mainView);
            }
            wrapper.addView(mainView);
        }
        parent = (ViewGroup) container.getParent();
        if (parent != mContentView) {
            if (parent != null) {
                parent.removeView(container);
            }
            mContentView.addView(container, COVER_SCREEN_PARAMS);
        }
        mUiController.attachSubWindow(tab);
    }


获取Tab的ViewContainer,获取container中的webview_wrapper控件,然后将tab对应的webView添加到其中,然后再将container添加到mContentView中


那mContentView是从哪里来的呢?


是通过实例化PhoneUi对象来的,在BaseUi构造函数中;
FrameLayout frameLayout = (FrameLayout) mActivity.getWindow()
    .getDecorView().findViewById(android.R.id.content);
LayoutInflater.from(mActivity)
    .inflate(R.layout.custom_screen, frameLayout);
mContentView = (FrameLayout) frameLayout.findViewById(R.id.main_content);


然后调用loadUrl来加载url
loadUrl(Tab tab, String url)-->loadUrl(Tab tab, String url, Map<String, String> headers)


if (tab != null) {
    dismissSubWindow(tab);
    tab.loadUrl(url, headers);
    mUi.onProgressChanged(tab);
}




Tab.java:
public void loadUrl(String url, Map<String, String> headers) {
    if (mMainView != null) {
        mPageLoadProgress = INITIAL_PROGRESS;
        mInPageLoad = true;
        mCurrentState = new PageState(mContext, false, url, null);
        mWebViewController.onPageStarted(this, mMainView, null);
        mMainView.loadUrl(url, headers);
    }
}



最终执行mMainView loadUrl方法加载url,显示对应url的网页。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值